/*
 * TaskThread.cpp
 *
 *  Created on: 2020年8月22日
 *      Author: chuanjiang.zh
 */

#include "TaskThread.h"
#include "CPollTimerQueue.h"

namespace comn
{

TaskThread::TaskThread():
	m_timerQueue(new CPollTimerQueue())
{
}

TaskThread::~TaskThread()
{
	if (isRunning())
	{
		stop();
	}

	m_timerQueue->clear();
	delete m_timerQueue;
}

void TaskThread::post(Task task)
{
	{
		std::lock_guard< std::mutex >	lock(m_mutex);
		m_taskQueue.push_back(task);
	}

	postEvent();
}

void TaskThread::clearTask()
{
	{
		std::lock_guard< std::mutex >	lock(m_mutex);
		m_taskQueue.clear();
	}

	postEvent();
}

void TaskThread::onIdle()
{
	int ms = m_timerQueue->poll();
	//if (ms < 0)
	//{
	//	ms = IDLE_DURATION * 10;
	//}

	timedwait(ms);
}

int TaskThread::run()
{
	while (!m_canExit)
	{
		if (!fetchAndHandle())
		{
			onIdle();
		}
	}
	return 0;
}

void TaskThread::doStop()
{
	postEvent();
}


bool TaskThread::fetchAndHandle()
{
	Task task;
	if (!fetchTask(task))
	{
		return false;
	}

	task();

	return true;
}

bool TaskThread::fetchTask(Task& task)
{
	bool got = false;
	std::lock_guard< std::mutex >	lock(m_mutex);
	if (m_taskQueue.size() > 0)
	{
		task = m_taskQueue.front();
		m_taskQueue.pop_front();
		got = true;
	}
	return got;
}

int TaskThread::addTimer(uint32_t ms, TimerTask task)
{
	int tid = m_timerQueue->addTimer(ms, task);

	postEvent();
	return tid;
}

int TaskThread::addElapse(uint32_t ms, TimerTask task)
{
	int tid = m_timerQueue->addElapse(ms, task);

	postEvent();
	return tid;
}

void TaskThread::cancelTimer(int tid)
{
	m_timerQueue->cancel(tid);

	postEvent();
}

void TaskThread::clearTimer()
{
	m_timerQueue->clear();

	postEvent();
}

int TaskThread::poll()
{
	return m_timerQueue->poll();
}

bool TaskThread::timedwait(int ms)
{
	return m_eventTask.timedwait(ms);
}

void TaskThread::postEvent()
{
	m_eventTask.post();
}

size_t TaskThread::getQueueSize()
{
	std::lock_guard< std::mutex >	lock(m_mutex);
	return m_taskQueue.size();
}


}